package com.alog.common.code;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockSyncQueue {
    private List<String> arr = new ArrayList<>();
    private static Lock initLock = new ReentrantLock();
    private Lock optLock = new ReentrantLock();
    private Condition consumerCondition = optLock.newCondition();
    private Condition productorCondition = optLock.newCondition();
    private int count = 0;
    private static volatile LockSyncQueue instance ;
    private LockSyncQueue(){}

    public static LockSyncQueue getInstance(){
        if(instance == null){
            initLock.lock();
            if(instance == null){
                instance = new LockSyncQueue();
            }
            initLock.unlock();
        }
        return instance;
    }


    public void add(){
        while(true){
            optLock.lock();
            if(arr.size() > 0){
                try {
                    productorCondition.await();
                    continue;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            arr.add((++count) + "");
            System.out.println(Thread.currentThread().getName() + " add " + count);
            consumerCondition.signalAll();
            optLock.unlock();
            break;
        }
    }

    public String poll(){
        String content = null;
        while(true){
            optLock.lock();
            if(arr.size() <= 0){
                try {
                    consumerCondition.await();
                    continue;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            content = arr.remove(0);
            System.out.println(Thread.currentThread().getName() + " poll " + content);
            productorCondition.signalAll();
            optLock.unlock();
            break;
        }
        return content;
    }
}
